package com.lingshu.app.utils;

import android.graphics.Bitmap;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import okio.Buffer;
import okio.BufferedSink;
import okio.BufferedSource;
import okio.ByteString;
import okio.Okio;
import okio.Sink;
import okio.Source;

/**
 * @author 于定金
 * @version 1.0
 * @Date 2024/1/19 9:12
 * @Description
 */
public class FileUtils {
    /**
     * 创建目录
     *
     * @param directory
     */
    public static void createDirectory(String directory) {
        File directoryFile = new File(directory);
        if (!directoryFile.exists()) {
            directoryFile.mkdirs();
        }
    }

    public static boolean checkIsExist(String directory) {
        File directoryFile = new File(directory);
        if (!directoryFile.exists()) {
            return false;
        }
        return true;
    }

    /**
     * 清空某个目录
     *
     * @param directory
     */
    public static void deleteDirectory(File directory) {
        if (directory.exists()) {
            if (directory.isDirectory()) {
                File[] files = directory.listFiles();
                if (files != null) {
                    for (File file : files) {
                        deleteDirectory(file);
                    }
                }
            }
            directory.delete();
        }
    }

    /**
     * 创建目录
     *
     * @param directoryFile
     */
    public static void createDirectory(File directoryFile) {
        if (directoryFile != null && directoryFile.isDirectory() && !directoryFile.exists()) {
            directoryFile.mkdirs();
        }
    }

    /**
     * 获取文件的目录
     *
     * @param filePath
     * @return
     */
    public static String getDirectory(String filePath) {
        File file = new File(filePath);
        return file.getParent();
    }

    /**
     * 获取绝对路径
     *
     * @param filePath
     * @return
     */
    public static String getAbsolutePath(String filePath) {
        File file = new File(filePath);
        return file.getAbsolutePath();
    }

    /**
     * 读取二进制文件
     *
     * @param filePath
     * @return
     * @throws IOException
     */
    public static byte[] readBinaryFile(String filePath) throws IOException {
        File file = new File(filePath);
        Source source = Okio.source(file);
        BufferedSource bufferedSource = Okio.buffer(source);
        byte[] bytes = bufferedSource.readByteArray();
        bufferedSource.close();
        source.close();
        return bytes;
    }

    /**
     * 将
     *
     * @param filePath
     * @return
     * @throws IOException
     */
    public static InputStream readFileToInputStream(String filePath) throws IOException {
        File file = new File(filePath);
        Source source = Okio.source(file);
        BufferedSource bufferedSource = Okio.buffer(source);
        InputStream inputStream = bufferedSource.inputStream();
        bufferedSource.close();
        source.close();
        return inputStream;
    }

    /**
     * 读取文本文件
     *
     * @param filePath
     * @return
     * @throws IOException
     */
    public static String readStringFile(String filePath) throws IOException {
        File file = new File(filePath);
        Source source = Okio.source(file);
        BufferedSource bufferedSource = Okio.buffer(source);
        String content = null;
        StringBuilder stringBuilder = new StringBuilder();
        while ((content = bufferedSource.readUtf8Line()) != null) {
            stringBuilder.append(content);
        }
        bufferedSource.close();
        source.close();
        return stringBuilder.toString();
    }

    /**
     * 文本写入
     *
     * @param filePath
     * @param content
     * @throws IOException
     */
    public static void writeStringFile(String filePath, String content) throws IOException {
        File file = new File(filePath);
        if (checkIsExist(getDirectory(filePath)) == false) {
            createDirectory(getDirectory(filePath));
        }
        if (!file.exists()) {
            file.createNewFile();
        }
        //获取sink对象
        Sink sink = Okio.sink(file);
        //获取sink缓冲对象
        BufferedSink bufferedSink = Okio.buffer(sink);
        //写入数据
        bufferedSink.writeUtf8(content);
        //关闭sink
        bufferedSink.close();
        sink.close();
    }

    /**
     * 将输入流写入到文件中
     *
     * @param inputStream
     * @param destinationFilePath
     * @throws IOException
     */
    public static void writeInputStreamToFile(InputStream inputStream, String destinationFilePath) throws IOException {
        File file = new File(destinationFilePath);
        Sink sink = Okio.sink(file);
        BufferedSink bufferedSink = Okio.buffer(sink);
        byte[] buffer = new byte[1024];
        int bytesRead = 0;
        while ((bytesRead = inputStream.read(buffer)) != -1) {
            bufferedSink.write(buffer, 0, bytesRead);
        }
        bufferedSink.close();
        sink.close();
    }

    public static void writeByteArrayToFile(byte[] byteArray, String destinationFilePath) throws IOException {
        File file = new File(destinationFilePath);
        Sink sink = Okio.sink(file);
        BufferedSink bufferedSink = Okio.buffer(sink);
        bufferedSink.write(byteArray);
        bufferedSink.close();
        sink.close();
    }

    /**
     * 对字符串反序列化
     *
     * @param byteString
     * @return
     * @throws IOException
     * @throws ClassNotFoundException
     */
    public static Object deserialize(ByteString byteString) throws IOException, ClassNotFoundException {
        Buffer buffer = new Buffer();
        buffer.write(byteString);
        try (ObjectInputStream objectIn = new ObjectInputStream(buffer.inputStream())) {
            Object result = objectIn.readObject();
            if (objectIn.read() != -1) throw new IOException("Unconsumed bytes in stream");
            return result;
        }
    }

    /**
     * 将对象序列化
     *
     * @param o
     * @return
     * @throws IOException
     */
    public static ByteString serialize(Object o) throws IOException {
        Buffer buffer = new Buffer();
        try (ObjectOutputStream objectOut = new ObjectOutputStream(buffer.outputStream())) {
            objectOut.writeObject(o);
        }
        return buffer.readByteString();
    }

    public static void encode(Bitmap bitmap, BufferedSink sink) throws IOException {
        int height = bitmap.getHeight();
        int width = bitmap.getWidth();

        int bytesPerPixel = 3;
        int rowByteCountWithoutPadding = (bytesPerPixel * width);
        int rowByteCount = ((rowByteCountWithoutPadding + 3) / 4) * 4;
        int pixelDataSize = rowByteCount * height;
        int bmpHeaderSize = 14;
        int dibHeaderSize = 40;

        // BMP Header
        sink.writeUtf8("BM"); // ID.
        sink.writeIntLe(bmpHeaderSize + dibHeaderSize + pixelDataSize); // File size.
        sink.writeShortLe(0); // Unused.
        sink.writeShortLe(0); // Unused.
        sink.writeIntLe(bmpHeaderSize + dibHeaderSize); // Offset of pixel data.

        // DIB Header
        sink.writeIntLe(dibHeaderSize);
        sink.writeIntLe(width);
        sink.writeIntLe(height);
        sink.writeShortLe(1);  // Color plane count.
        sink.writeShortLe(bytesPerPixel * Byte.SIZE);
        sink.writeIntLe(0);    // No compression.
        sink.writeIntLe(16);   // Size of bitmap data including padding.
        sink.writeIntLe(2835); // Horizontal print resolution in pixels/meter. (72 dpi).
        sink.writeIntLe(2835); // Vertical print resolution in pixels/meter. (72 dpi).
        sink.writeIntLe(0);    // Palette color count.
        sink.writeIntLe(0);    // 0 important colors.

        // Pixel data.
        for (int y = height - 1; y >= 0; y--) {
            for (int x = 0; x < width; x++) {
                //sink.writeByte(bitmap.blue(x, y));
                //sink.writeByte(bitmap.green(x, y));
                //sink.writeByte(bitmap.red(x, y));
            }

            // Padding for 4-byte alignment.
            for (int p = rowByteCountWithoutPadding; p < rowByteCount; p++) {
                sink.writeByte(0);
            }
        }
    }
}
